package br.com.sgmf.web.managedbean;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import br.com.sgmf.enums.StatusOS;
import br.com.sgmf.model.ItemOrdem;
import br.com.sgmf.model.Modelo;
import br.com.sgmf.model.OrdemServico;
import br.com.sgmf.model.Peca;
import br.com.sgmf.model.Veiculo;
import br.com.sgmf.service.OrdemServicoService;
import br.com.sgmf.service.PecaService;
import br.com.sgmf.service.VeiculoService;

@Component
@ManagedBean
@RequestScoped
public class OrdemServicoBean {

	private static final String VERIFICACAO_ORDEM_SERVICO = "Só podem ser cadastradas peças quando a Ordem de Serviço estiver com status concluído";
	private static final String BUSCAR_PECA = "Necessário buscar peca(s)";
	private static final String BUSCAR_VEICULO = "Necessário buscar veículo";
	private static final String ORDEM_DE_SERVICO_SALVA_COM_SUCESSO = "Ordem de Serviço salva com sucesso!";
	private static final String ERRO_AO_SALVAR_ORDEM_DE_SERVICO = "Erro ao salvar Ordem de Serviço";
	private static final String ORDEM_DE_SERVICO_EXCLUIDA_COM_SUCESSO = null;
	private static final String ERRO_AO_EXCLUIR_ORDEM_DE_SERVICO = null;

	private OrdemServico ordemServico;
	private Veiculo veiculo;
	private Peca peca;

	private List<OrdemServico> ordensServico;
	private List<Veiculo> veiculos;
	private List<Peca> pecas;
	private Set<ItemOrdem> itensOrdem;

	private Date data;
	private String placa;
	private String nome;

	private List<OrdemServico> filteredOrdemServico;

	@Autowired
	private VeiculoService veiculoService;

	@Autowired
	private PecaService pecaService;

	@Autowired
	private OrdemServicoService ordemServicoService;

	@PostConstruct
	public void inicializar() {
		ordensServico = ordemServicoService.findAll();
		ordemServico = new OrdemServico();
		itensOrdem = new HashSet<>();
		data = new Date();
		filteredOrdemServico = null;
	}

	public void novo() {
		ordemServico = new OrdemServico();
		veiculo = null;
		peca = null;
		veiculos = null;
		pecas = null;
		itensOrdem = new HashSet<>();
		data = new Date();
		placa = null;
		nome = null;
	}

	public String salvar() {
		FacesContext context = FacesContext.getCurrentInstance();
		FacesMessage message;
		if (veiculo == null) {
			message = new FacesMessage(FacesMessage.SEVERITY_WARN,
					BUSCAR_VEICULO, null);
		} else if (CollectionUtils.isNotEmpty(itensOrdem)
				&& (StatusOS.SERVICO_CONCLUIDO != ordemServico.getStatusOS())) {
			message = new FacesMessage(FacesMessage.SEVERITY_WARN,
					VERIFICACAO_ORDEM_SERVICO, null);
		} else if (CollectionUtils.isEmpty(itensOrdem)
				&& (StatusOS.SERVICO_CONCLUIDO == ordemServico.getStatusOS())) {
			message = new FacesMessage(FacesMessage.SEVERITY_WARN, BUSCAR_PECA,
					null);
		} else {
			try {
				ordemServicoService.saveOrUpdate(ordemServico, data, veiculo,
						itensOrdem);
				message = new FacesMessage(FacesMessage.SEVERITY_INFO,
						ORDEM_DE_SERVICO_SALVA_COM_SUCESSO, null);
				inicializar();
			} catch (Exception e) {
				message = new FacesMessage(FacesMessage.SEVERITY_INFO,
						ERRO_AO_SALVAR_ORDEM_DE_SERVICO, null);
				e.printStackTrace();
			}
		}
		context.addMessage(null, message);
		return null;
	}

	public void editar(OrdemServico ordemServico) {
		this.veiculo = ordemServico.getVeiculo();
		this.ordemServico = ordemServico;
	}

	public String excluir(OrdemServico ordemServico) {
		FacesContext context = FacesContext.getCurrentInstance();
		FacesMessage message;

		try {
			ordemServicoService.delete(ordemServico);
			message = new FacesMessage(FacesMessage.SEVERITY_INFO,
					ORDEM_DE_SERVICO_EXCLUIDA_COM_SUCESSO, null);
			inicializar();
		} catch (Exception e) {
			message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
					ERRO_AO_EXCLUIR_ORDEM_DE_SERVICO, null);
			e.printStackTrace();
		}

		context.addMessage(null, message);
		return null;
	}

	public List<Veiculo> buscarVeiculo() {
		veiculos = veiculoService.findByPlaca(placa);
		placa = null;
		return veiculos;
	}

	public void adicionarVeiculo(Veiculo veiculo) {
		if (CollectionUtils.isNotEmpty(itensOrdem)) {
			itensOrdem = new HashSet<ItemOrdem>();
		}
		this.veiculo = veiculo;
	}

	public List<Peca> buscarPeca() {
		if (veiculo != null) {
			Modelo modelo = veiculo.getModelo();
			pecas = pecaService.findByNomeAndModelo(nome, modelo.getNome());
		} else {
			pecas = pecaService.findByNome(nome);
		}
		nome = null;
		return pecas;
	}

	public void adicionarPeca(Peca peca) {
		ItemOrdem itemOrdem = new ItemOrdem(1, peca);
		itensOrdem.add(itemOrdem);
	}

	public void incrementarItemOrdem(ItemOrdem itemOrdem) {
		itemOrdem.incrementAndGet();
	}

	public void decrementarItemOrdem(ItemOrdem itemOrdem) {
		if (itemOrdem.decrementAndGet() <= 0) {
			removerItemOrdem(itemOrdem);
		}
	}

	public void removerItemOrdem(ItemOrdem itemOrdem) {
		itensOrdem.remove(itemOrdem);
	}

	public StatusOS[] getStatusOS() {
		return StatusOS.values();
	}

	public StatusOS[] getStatusLiberacao() {
		StatusOS[] statusOS = { StatusOS.SERVICO_EM_LIBERACAO };
		return statusOS;
	}

	public OrdemServico getOrdemServico() {
		return ordemServico;
	}

	public void setOrdemServico(OrdemServico ordemServico) {
		this.ordemServico = ordemServico;
	}

	public Veiculo getVeiculo() {
		return veiculo;
	}

	public void setVeiculo(Veiculo veiculo) {
		this.veiculo = veiculo;
	}

	public Peca getPeca() {
		return peca;
	}

	public void setPeca(Peca peca) {
		this.peca = peca;
	}

	public List<OrdemServico> getOrdensServico() {
		return ordensServico;
	}

	public void setOrdensServico(List<OrdemServico> ordensServico) {
		this.ordensServico = ordensServico;
	}

	public List<Veiculo> getVeiculos() {
		return veiculos;
	}

	public void setVeiculos(List<Veiculo> veiculos) {
		this.veiculos = veiculos;
	}

	public List<Peca> getPecas() {
		return pecas;
	}

	public void setPecas(List<Peca> pecas) {
		this.pecas = pecas;
	}

	public Set<ItemOrdem> getItensOrdem() {
		return itensOrdem;
	}

	public void setItensOrdem(Set<ItemOrdem> itensOrdem) {
		this.itensOrdem = itensOrdem;
	}

	public Date getData() {
		return data;
	}

	public void setData(Date data) {
		this.data = data;
	}

	public String getPlaca() {
		return placa;
	}

	public void setPlaca(String placa) {
		this.placa = placa;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public List<OrdemServico> getFilteredOrdemServico() {
		return filteredOrdemServico;
	}

	public void setFilteredOrdemServico(List<OrdemServico> filteredOrdemServico) {
		this.filteredOrdemServico = filteredOrdemServico;
	}

	public VeiculoService getVeiculoService() {
		return veiculoService;
	}

	public void setVeiculoService(VeiculoService veiculoService) {
		this.veiculoService = veiculoService;
	}

	public PecaService getPecaService() {
		return pecaService;
	}

	public void setPecaService(PecaService pecaService) {
		this.pecaService = pecaService;
	}

	public OrdemServicoService getOrdemServicoService() {
		return ordemServicoService;
	}

	public void setOrdemServicoService(OrdemServicoService ordemServicoService) {
		this.ordemServicoService = ordemServicoService;
	}

}
